home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MISC.SWG / 0107_Hand Scanner Code.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-24  |  15KB  |  429 lines

  1. unit RJScan;
  2.  
  3. {******************************}
  4. {                              }
  5. {            RJScan            }
  6. {                              }
  7. {             v1.1             }
  8. {                              }
  9. {                              }
  10. {              by              }
  11. {                              }
  12. {        Roland Skinner        }
  13. {                              }
  14. {      Copyright (c) 1992      }
  15. {                              }
  16. {         RJS Software         }
  17. {                              }
  18. {    Released to the public    }
  19. {         domain 1994.         }
  20. {                              }
  21. {******************************}
  22.  
  23.  
  24. { Implements scanning ability for the DFI HS-3000 PLUS HANDY SCANNER or }
  25. { other 100% compatible hand-scanners (including certain GeniScans).    }
  26.  
  27. { NOTE - This unit may be overlayed.                                    }
  28. {      - This unit requires Turbo Pascal 6 (or above).                  }
  29.  
  30. {$B-,D-,F+,G-,I-,L-,O+,R-,S-,V-,X-}
  31.  
  32. {=============================================================================}
  33.  
  34. interface
  35.  
  36. {-----------------------------------------------------------------------------}
  37.  
  38.   const
  39.     AnyResolution = 0;
  40.  
  41. {-----------------------------------------------------------------------------}
  42.  
  43.   type
  44.     ScanError = (scOK,scNoScanner,scInvalidResolution,scIncorrectResolution,
  45.                  scInvalidImageWidth);
  46.  
  47. {-----------------------------------------------------------------------------}
  48.  
  49.   type
  50.     ScanLineBufferProc = function(LineNumber : Integer) : Pointer;
  51.                          { NOTE - This function should return  the  address }
  52.                          {        of the scan-buffer for the "LineNumber"th }
  53.                          {        line. First line is number 0.             }
  54.     DisplayScannedLineProc = procedure(LineNumber : Integer);
  55.                              { NOTE - This  procedure  should  display  (if }
  56.                              {        necessary)  the  "LineNumber"th  line }
  57.                              {        that was scanned in.  First  line  is }
  58.                              {        number 0.                             }
  59.     StopScanningProc = function : Boolean;
  60.                        { NOTE - This function should return "False", unless }
  61.                        {        some  event  has  occurred  which  requires }
  62.                        {        scanning to stop.                           }
  63.  
  64. {-----------------------------------------------------------------------------}
  65.  
  66.   function  ScanImage(DesiredResolution,MaxLinesToScan,BytesPerLine : Integer;
  67.                       ScanLineBuffer : ScanLineBufferProc;
  68.                       DisplayScannedLine : DisplayScannedLineProc;
  69.                       StopScanning : StopScanningProc) : ScanError;
  70.     {- This function will scan an image  with  width  8*"BytesPerLine"  and }
  71.     {  height "MaxLinesToScan". It is possible to specify the resolution at }
  72.     {  which to scan the image  in  "DesiredResolution"  (100,200,300,400). }
  73.     {  If the resolution set on the scanner is different to that specified, }
  74.     {  then   the   "scIncorrectResolution"   error   will   be   returned. }
  75.     {  If "DesiredResolution" is "AnyResolution", then any resolution  will }
  76.     {  be allowed. "scInvalidResolution" will be returned if  a  resolution }
  77.     {  other than 100,200,300,400 or "AnyResolution" is specified.          }
  78.     {  "ScanLineBuffer",  "DisplayScannedLine"   and   "StopScanning"   are }
  79.     {  procedures/functions whose functions are discussed above. These must }
  80.     {  be FAR procedures/functions.                                         }
  81.     {  If "BytesPerLine" is too  large  for  the  scanner-resolution,  then }
  82.     {  "scInvalidImageWidth" will be returned.                              }
  83.     {  If scanner is not installed then "scNoScanner" is returned.          }
  84.     {  If successful, then "scOK" will be returned.                         }
  85.     {  This function may not work with  certain hand-scanners (if  so,  use }
  86.     {  "GenericScanImage").                                                 }
  87.   function  GenericScanImage(MaxLinesToScan,BytesPerLine : Integer;
  88.                              ScanLineBuffer : ScanLineBufferProc;
  89.                              DisplayScannedLine : DisplayScannedLineProc;
  90.                              StopScanning : StopScanningProc) : ScanError;
  91.     {- This  function  will  scan  an  image  in  an  analogous  manner  as }
  92.     {  "ScanImage". However, it does not do any checks for valid resolution }
  93.     {  or image-width. This is to allow compatibility for scanners which do }
  94.     {  not allow for scan-resolution selection.                             }
  95.     {  "scOK", "scNoScanner" and "scInvalidImageWidth" may be  returned  by }
  96.     {  this function. Refer to "ScanImage" for a discussion about these.    }
  97.   function  ScannerIsInstalled : Boolean;
  98.     {- Returns installed-status of scanner.                                 }
  99.   function  ResolutionOfScanner : Integer;
  100.     {- Returns the resolution  set  on  the  scanner.  If  scanner  is  not }
  101.     {  installed, then -1 will be returned.                                 }
  102.     {  This function may not work with certain hand-scanners.               }
  103.  
  104. {=============================================================================}
  105.  
  106. implementation
  107.  
  108. {-----------------------------------------------------------------------------}
  109.  
  110.   const
  111.     MaxBytesPerLine : Array[1..4] of Byte = (50,102,154,205);
  112.  
  113. {-----------------------------------------------------------------------------}
  114.  
  115.   var
  116.     ScannerInstalled        : Boolean;
  117.     ScannerResolution       : Word;
  118.     ScannerResolution100    : Byte;
  119.     DMAChannel              : Byte;
  120.     DMAPageRegister         : Word;
  121.     DMACurAddrRegister      : Word;
  122.     DMACurWordCountRegister : Word;
  123.     DMAClearSingleMaskBit   : Byte;
  124.     DMASetSingleMaskBit     : Byte;
  125.     DMAModeRegisterSetting  : Byte;
  126.     DMAWriteRequest         : Byte;
  127.     DMATerminalCountReached : Byte;
  128.  
  129. {-----------------------------------------------------------------------------}
  130.  
  131.   procedure DetermineScannerResolution; assembler;
  132.   var
  133.     Data : Byte;
  134.   asm
  135.     xor     ax,ax
  136.     jmp     @Start
  137.   @ResSettings:
  138.     db      21h,41h,51h,71h
  139.   @Start:
  140.     mov     dx,27Bh
  141.     mov     cx,300
  142.   @1:
  143.     in      al,dx
  144.     and     al,10000000b
  145.     jnz     @1
  146.   @2:
  147.     in      al,dx
  148.     and     al,10000000b
  149.     jz      @2
  150.     loop    @1
  151.   @3:
  152.     in      al,dx
  153.     and     al,10000000b
  154.     jnz     @3
  155.   @4:
  156.     in      al,dx
  157.     and     al,00100100b
  158.     shr     al,1
  159.     shr     al,1
  160.     or      ah,al
  161.     shr     al,1
  162.     shr     al,1
  163.     or      ah,al
  164.     and     ah,00000011b
  165.     xor     al,al
  166.     xchg    al,ah
  167.     mov     bl,4
  168.     sub     bl,al
  169.     mov     al,bl
  170.     push    ax
  171.     mov     bx,OFFSET (@ResSettings-1)
  172.     add     bx,ax
  173.     mov     al,[cs:bx]
  174.     mov     dx,27Ah
  175.     out     dx,al
  176.     mov     Data,al
  177.     pop     ax
  178.     mov     ScannerResolution100,al
  179.     mov     cx,100
  180.     mul     cx
  181.     mov     ScannerResolution,ax
  182.   end;
  183.  
  184. {-----------------------------------------------------------------------------}
  185.  
  186.   procedure DetermineScannerDMA; assembler;
  187.   asm
  188.     mov     dx,27Bh
  189.     in      al,dx
  190.     and     al,00001010b
  191.     cmp     al,00001000b
  192.     je      @UseDMA1
  193.     cmp     al,00000010b
  194.     je      @UseDMA3
  195.     jmp     @NoDMA
  196.   @UseDMA1:
  197.     mov     DMAChannel,1
  198.     mov     DMAPageRegister,        83h
  199.     mov     DMACurAddrRegister,     02h
  200.     mov     DMACurWordCountRegister,03h
  201.     mov     DMAClearSingleMaskBit,  00000001b
  202.     mov     DMASetSingleMaskBit,    00000101b
  203.     mov     DMAModeRegisterSetting, 01000101b
  204.     mov     DMAWriteRequest,        00000001b
  205.     mov     DMATerminalCountReached,00000010b
  206.     jmp     @Exit
  207.   @UseDMA3:
  208.     mov     DMAChannel,3
  209.     mov     DMAPageRegister,        82h
  210.     mov     DMACurAddrRegister,     06h
  211.     mov     DMACurWordCountRegister,07h
  212.     mov     DMAClearSingleMaskBit,  00000011b
  213.     mov     DMASetSingleMaskBit,    00000111b
  214.     mov     DMAModeRegisterSetting, 01000111b
  215.     mov     DMAWriteRequest,        00000011b
  216.     mov     DMATerminalCountReached,00001000b
  217.     jmp     @Exit
  218.   @NoDMA:
  219.     mov     DMAChannel,0
  220.   @Exit:
  221.   end;
  222.  
  223. {-----------------------------------------------------------------------------}
  224.  
  225.   procedure TurnScannerOn; assembler;
  226.   asm
  227.     mov     dx,27Ah
  228.     mov     al,01h
  229.     out     dx,al
  230.   end;
  231.  
  232. {-----------------------------------------------------------------------------}
  233.  
  234.   procedure TurnScannerOff; assembler;
  235.   asm
  236.     mov     dx,27Ah
  237.     mov     al,00h
  238.     out     dx,al
  239.   end;
  240.  
  241. {-----------------------------------------------------------------------------}
  242.  
  243.   procedure DMADelay; assembler;
  244.   asm
  245.     nop
  246.     nop
  247.     nop
  248.   end;
  249.  
  250. {-----------------------------------------------------------------------------}
  251.  
  252.   function  DoScan(MaxLinesToScan,BytesPerLine : Integer;
  253.                    ScanLineBuffer : ScanLineBufferProc;
  254.                    DisplayScannedLine : DisplayScannedLineProc;
  255.                    StopScanning : StopScanningProc) : ScanError;
  256.   var
  257.     LinesScanned : Integer;
  258.     ScanBuffer   : Pointer;
  259.     WidthToScan  : Word absolute BytesPerLine;
  260.     QuitScanning : Boolean;
  261.   begin
  262.     if (BytesPerLine>0) and (BytesPerLine<=MaxBytesPerLine[ScannerResolution100]) then
  263.     begin
  264.       LinesScanned := 0;
  265.       QuitScanning := False;
  266.       repeat
  267.         ScanBuffer := ScanLineBuffer(LinesScanned);
  268.         asm
  269.         {-Disable DMA transfer }
  270.           mov     al,DMASetSingleMaskBit
  271.           out     0Ah,al
  272.           call    DMADelay;
  273.           mov     al,DMAModeRegisterSetting
  274.           out     0Bh,al
  275.           call    DMADelay
  276.         {-Setup Buffer address }
  277.           les     di,ScanBuffer
  278.           mov     dx,es
  279.           mov     al,dh
  280.           mov     cl,4
  281.           shl     dx,cl
  282.           shr     al,cl
  283.           add     dx,di
  284.           adc     al,0
  285.           mov     cx,dx
  286.           mov     dx,DMAPageRegister
  287.           out     dx,al
  288.           call    DMADelay
  289.           out     0Ch,al
  290.           call    DMADelay
  291.           mov     dx,DMACurAddrRegister
  292.           mov     al,cl
  293.           out     dx,al
  294.           call    DMADelay
  295.           mov     al,ch
  296.           out     dx,al
  297.           call    DMADelay
  298.         {-Setup bytes to transfer }
  299.           out     0Ch,al
  300.           call    DMADelay
  301.           mov     ax,WidthToScan
  302.           dec     ax
  303.           mov     dx,DMACurWordCountRegister
  304.           out     dx,al
  305.           call    DMADelay
  306.           mov     al,ah
  307.           out     dx,al
  308.         {-Start DMA transfer }
  309.           mov     dx,27Bh
  310.           out     dx,al
  311.           dec     dx
  312.           in      al,dx                 { DX = 027Ah }
  313.           mov     al,DMAWriteRequest
  314.           out     09h,al
  315.           call    DMADelay
  316.           mov     al,DMAClearSingleMaskBit
  317.           out     0Ah,al
  318.         end;
  319.       {-Scan line }
  320.         asm
  321.           mov     bl,DMATerminalCountReached
  322.         @1:
  323.           in      al,08h
  324.           and     al,bl
  325.           cmp     al,bl
  326.           je      @2
  327.           push    bx
  328.           call    StopScanning
  329.           pop     bx
  330.           or      al,al
  331.           jz      @1
  332.           mov     QuitScanning,True
  333.         @2:
  334.         end;
  335.         DisplayScannedLine(LinesScanned);
  336.         Inc(LinesScanned);
  337.       until (LinesScanned=MaxLinesToScan) or QuitScanning;
  338.       DoScan := scOK;
  339.     end
  340.     else
  341.       DoScan := scInvalidImageWidth;
  342.   end;
  343.  
  344. {-----------------------------------------------------------------------------}
  345.  
  346.   function  ScanImage(DesiredResolution,MaxLinesToScan,BytesPerLine : Integer;
  347.                       ScanLineBuffer : ScanLineBufferProc;
  348.                       DisplayScannedLine : DisplayScannedLineProc;
  349.                       StopScanning : StopScanningProc) : ScanError;
  350.   begin
  351.     if ScannerInstalled then
  352.     begin
  353.       if (DesiredResolution=AnyResolution) or ((DesiredResolution div 100) in [1..4]) then
  354.       begin
  355.         TurnScannerOn;
  356.         DetermineScannerResolution;
  357.         if (DesiredResolution=AnyResolution) or (DesiredResolution=ScannerResolution) then
  358.           ScanImage := DoScan(MaxLinesToScan,BytesPerLine,
  359.                               ScanLineBuffer,DisplayScannedLine,StopScanning)
  360.         else
  361.           ScanImage := scIncorrectResolution;
  362.         TurnScannerOff;
  363.       end
  364.       else
  365.         ScanImage := scInvalidResolution;
  366.     end
  367.     else
  368.       ScanImage := scNoScanner;
  369.   end;
  370.  
  371. {-----------------------------------------------------------------------------}
  372.  
  373.   function  GenericScanImage(MaxLinesToScan,BytesPerLine : Integer;
  374.                              ScanLineBuffer : ScanLineBufferProc;
  375.                              DisplayScannedLine : DisplayScannedLineProc;
  376.                              StopScanning : StopScanningProc) : ScanError;
  377.   begin
  378.     if ScannerInstalled then
  379.     begin
  380.       TurnScannerOn;
  381.       ScannerResolution100 := 4;
  382.       GenericScanImage := DoScan(MaxLinesToScan,BytesPerLine,
  383.                           ScanLineBuffer,DisplayScannedLine,StopScanning);
  384.       TurnScannerOff;
  385.     end
  386.     else
  387.       GenericScanImage := scNoScanner;
  388.   end;
  389.  
  390. {-----------------------------------------------------------------------------}
  391.  
  392.   procedure DetermineScannerPresence;
  393.   begin
  394.     TurnScannerOn;
  395.     DetermineScannerDMA;
  396.     TurnScannerOff;
  397.     ScannerInstalled := (DMAChannel<>0);
  398.   end;
  399.  
  400. {-----------------------------------------------------------------------------}
  401.  
  402.   function  ScannerIsInstalled : Boolean;
  403.   begin
  404.     ScannerIsInstalled := ScannerInstalled;
  405.   end;
  406.  
  407. {-----------------------------------------------------------------------------}
  408.  
  409.   function  ResolutionOfScanner : Integer;
  410.   begin
  411.     if ScannerInstalled then
  412.     begin
  413.       TurnScannerOn;
  414.       DetermineScannerResolution;
  415.       TurnScannerOff;
  416.       ResolutionOfScanner := ScannerResolution;
  417.     end
  418.     else
  419.       ResolutionOfScanner := -1;
  420.   end;
  421.  
  422. {-----------------------------------------------------------------------------}
  423.  
  424. begin
  425.   DetermineScannerPresence;
  426. end.
  427.  
  428. {=============================================================================}
  429.